

#include <iostream>
#include <mutex>

template <typename F>
class lazy_val {
private:
    F m_computation;
    mutable std::once_flag m_value_flag;
    mutable decltype(m_computation()) m_cache;

public:
    lazy_val(F func)
        : m_computation(func)
    {
    }

    operator const decltype(m_computation()) & () const
    {
        std::call_once(m_value_flag, [this]() { m_cache = m_computation(); });
        return m_cache;
    }
};

template <typename F>
inline lazy_val<F> make_lazy_val(F&& computation)
{
    return lazy_val<F>(std::forward<F>(computation));
}

int main()
{
    int a = 1, b = 2;
    auto c = [a, b]() { return a + b; };
    auto laze_val = make_lazy_val(c);
    std::cout << "laze_val: " << (int)laze_val << std::endl;
    std::cout << "laze_val: " << laze_val << std::endl;
    std::cout << "laze_val: " << static_cast<int>(laze_val) << std::endl;
    return 0;
}